home *** CD-ROM | disk | FTP | other *** search
/ Aminet 49 / Aminet 49 (2002)(GTI - Schatztruhe)[!][Jun 2002].iso / Aminet / text / misc / xsltproc.lha / xsltproc / xsltproc.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-11-10  |  14.4 KB  |  553 lines

  1. /*
  2.  * xsltproc.c: user program for the XSL Transformation 1.0 engine
  3.  *
  4.  * See Copyright for the status of this software.
  5.  *
  6.  * daniel@veillard.com
  7.  */
  8.  
  9. #include "libxslt/libxslt.h"
  10. #include "libexslt/exslt.h"
  11. #ifdef HAVE_STRING_H
  12. #include <string.h>
  13. #endif
  14. #ifdef HAVE_SYS_TIME_H
  15. #include <sys/time.h>
  16. #endif
  17. #ifdef HAVE_SYS_STAT_H
  18. #include <sys/stat.h>
  19. #endif
  20. #ifdef HAVE_UNISTD_H
  21. #include <unistd.h>
  22. #endif
  23. #ifdef HAVE_STDLIB_H
  24. #include <stdlib.h>
  25. #endif
  26. #ifdef HAVE_STDARG_H
  27. #include <stdarg.h>
  28. #endif
  29. #include <libxml/xmlmemory.h>
  30. #include <libxml/debugXML.h>
  31. #include <libxml/HTMLtree.h>
  32. #include <libxml/xmlIO.h>
  33. #ifdef LIBXML_DOCB_ENABLED
  34. #include <libxml/DOCBparser.h>
  35. #endif
  36. #ifdef LIBXML_XINCLUDE_ENABLED
  37. #include <libxml/xinclude.h>
  38. #endif
  39. #ifdef LIBXML_CATALOG_ENABLED
  40. #include <libxml/catalog.h>
  41. #endif
  42. #include <libxml/parserInternals.h>
  43.  
  44. #include <libxslt/xslt.h>
  45. #include <libxslt/xsltInternals.h>
  46. #include <libxslt/transform.h>
  47. #include <libxslt/xsltutils.h>
  48. #include <libxslt/extensions.h>
  49.  
  50. #include <libexslt/exsltconfig.h>
  51.  
  52. #ifdef WIN32
  53. #ifdef _MSC_VER
  54. #include <winsock2.h>
  55. #pragma comment(lib, "ws2_32.lib")
  56. #define gettimeofday(p1,p2)
  57. #endif /* _MS_VER */
  58. #else /* WIN32 */
  59. #if defined(HAVE_SYS_TIME_H)
  60. #include <sys/time.h>
  61. #elif defined(HAVE_TIME_H)
  62. #include <time.h>
  63. #endif
  64. #endif /* WIN32 */
  65.  
  66. #ifndef HAVE_STAT
  67. #  ifdef HAVE__STAT
  68.      /* MS C library seems to define stat and _stat. The definition
  69.       *         is identical. Still, mapping them to each other causes a warning. */
  70. #    ifndef _MSC_VER
  71. #      define stat(x,y) _stat(x,y)
  72. #    endif
  73. #    define HAVE_STAT
  74. #  endif
  75. #endif
  76.  
  77. xmlParserInputPtr xmlNoNetExternalEntityLoader(const char *URL,
  78.                                            const char *ID,
  79.                            xmlParserCtxtPtr ctxt);
  80.  
  81. static int debug = 0;
  82. static int repeat = 0;
  83. static int timing = 0;
  84. static int novalid = 0;
  85. static int noout = 0;
  86. #ifdef LIBXML_DOCB_ENABLED
  87. static int docbook = 0;
  88. #endif
  89. #ifdef LIBXML_HTML_ENABLED
  90. static int html = 0;
  91. #endif
  92. #ifdef LIBXML_XINCLUDE_ENABLED
  93. static int xinclude = 0;
  94. #endif
  95. static int profile = 0;
  96.  
  97. static const char *params[16 + 1];
  98. static int nbparams = 0;
  99. static const char *output = NULL;
  100.  
  101. /*
  102.  * Internal timing routines to remove the necessity to have unix-specific
  103.  * function calls
  104.  */
  105.  
  106. #if defined(HAVE_GETTIMEOFDAY)
  107. static struct timeval begin, end;
  108. /*
  109.  * startTimer: call where you want to start timing
  110.  */
  111. static void startTimer(void)
  112. {
  113.     gettimeofday(&begin,NULL);
  114. }
  115. /*
  116.  * endTimer: call where you want to stop timing and to print out a
  117.  *           message about the timing performed; format is a printf
  118.  *           type argument
  119.  */
  120. static void endTimer(const char *format, ...)
  121. {
  122.     long msec;
  123.     va_list ap;
  124.  
  125.     gettimeofday(&end, NULL);
  126.     msec = end.tv_sec - begin.tv_sec;
  127.     msec *= 1000;
  128.     msec += (end.tv_usec - begin.tv_usec) / 1000;
  129.  
  130. #ifndef HAVE_STDARG_H
  131. #error "endTimer required stdarg functions"
  132. #endif
  133.     va_start(ap, format);
  134.     vfprintf(stderr,format,ap);
  135.     va_end(ap);
  136.  
  137.     fprintf(stderr, " took %ld ms\n", msec);
  138. }
  139. #elif defined(HAVE_TIME_H)
  140. /*
  141.  * No gettimeofday function, so we have to make do with calling clock.
  142.  * This is obviously less accurate, but there's little we can do about
  143.  * that.
  144.  */
  145.  
  146. clock_t begin, end;
  147. static void startTimer(void)
  148. {
  149.     begin=clock();
  150. }
  151. static void endTimer(char *format, ...)
  152. {
  153.     long msec;
  154.     va_list ap;
  155.  
  156.     end=clock();
  157.     msec = ((end-begin) * 1000) / CLOCKS_PER_SEC;
  158.  
  159. #ifndef HAVE_STDARG_H
  160. #error "endTimer required stdarg functions"
  161. #endif
  162.     va_start(ap, format);
  163.     vfprintf(stderr,format,ap);
  164.     va_end(ap);
  165.     fprintf(stderr, " took %ld ms\n", msec);
  166. }
  167. #else
  168. /*
  169.  * We don't have a gettimeofday or time.h, so we just don't do timing
  170.  */
  171. static void startTimer(void)
  172. {
  173.   /*
  174.    * Do nothing
  175.    */
  176. }
  177. static void endTimer(char *format, ...)
  178. {
  179.   /*
  180.    * We cannot do anything because we don't have a timing function
  181.    */
  182. #ifdef HAVE_STDARG_H
  183.     va_start(ap, format);
  184.     vfprintf(stderr,format,ap);
  185.     va_end(ap);
  186.     fprintf(stderr, " was not timed\n", msec);
  187. #else
  188.   /* We don't have gettimeofday, time or stdarg.h, what crazy world is
  189.    * this ?!
  190.    */
  191. #endif
  192. }
  193. #endif
  194.  
  195. static void
  196. xsltProcess(xmlDocPtr doc, xsltStylesheetPtr cur, const char *filename) {
  197.     xmlDocPtr res;
  198.  
  199. #ifdef LIBXML_XINCLUDE_ENABLED
  200.     if (xinclude) {
  201.     if (timing)
  202.         startTimer();
  203.     xmlXIncludeProcess(doc);
  204.     if (timing) {
  205.         endTimer("XInclude processing %s", filename);
  206.     }
  207.     }
  208. #endif
  209.     if (timing)
  210.         startTimer();
  211.     if (output == NULL) {
  212.     if (repeat) {
  213.         int j;
  214.  
  215.         for (j = 1; j < repeat; j++) {
  216.         res = xsltApplyStylesheet(cur, doc, params);
  217.         xmlFreeDoc(res);
  218.         xmlFreeDoc(doc);
  219. #ifdef LIBXML_HTML_ENABLED
  220.         if (html)
  221.             doc = htmlParseFile(filename, NULL);
  222.         else
  223. #endif
  224. #ifdef LIBXML_DOCB_ENABLED
  225.         if (docbook)
  226.             doc = docbParseFile(filename, NULL);
  227.         else
  228. #endif
  229.             doc = xmlParseFile(filename);
  230.         }
  231.     }
  232.     if (profile) {
  233.         res = xsltProfileStylesheet(cur, doc, params, stderr);
  234.     } else {
  235.         res = xsltApplyStylesheet(cur, doc, params);
  236.     }
  237.     if (timing) {
  238.         if (repeat)
  239.         endTimer("Applying stylesheet %d times", repeat);
  240.         else
  241.         endTimer("Applying stylesheet");
  242.     }
  243.     xmlFreeDoc(doc);
  244.     if (res == NULL) {
  245.         fprintf(stderr, "no result for %s\n", filename);
  246.         return;
  247.     }
  248.     if (noout) {
  249.         xmlFreeDoc(res);
  250.         return;
  251.     }
  252. #ifdef LIBXML_DEBUG_ENABLED
  253.     if (debug)
  254.         xmlDebugDumpDocument(stdout, res);
  255.     else {
  256. #endif
  257.         if (cur->methodURI == NULL) {
  258.         if (timing)
  259.             startTimer();
  260.         xsltSaveResultToFile(stdout, res, cur);
  261.         if (timing)
  262.             endTimer("Saving result");
  263.         } else {
  264.         if (xmlStrEqual
  265.             (cur->method, (const xmlChar *) "xhtml")) {
  266.             fprintf(stderr, "non standard output xhtml\n");
  267.             if (timing)
  268.             startTimer();
  269.             xsltSaveResultToFile(stdout, res, cur);
  270.             if (timing)
  271.             endTimer("Saving result");
  272.         } else {
  273.             fprintf(stderr,
  274.                 "Unsupported non standard output %s\n",
  275.                 cur->method);
  276.         }
  277.         }
  278. #ifdef LIBXML_DEBUG_ENABLED
  279.     }
  280. #endif
  281.  
  282.     xmlFreeDoc(res);
  283.     } else {
  284.     xsltRunStylesheet(cur, doc, params, output, NULL, NULL);
  285.     if (timing)
  286.         endTimer("Running stylesheet and saving result");
  287.     xmlFreeDoc(doc);
  288.     }
  289. }
  290.  
  291. static void usage(const char *name) {
  292.     printf("Usage: %s [options] stylesheet file [file ...]\n", name);
  293.     printf("   Options:\n");
  294.     printf("      --version or -V: show the version of libxml and libxslt used\n");
  295.     printf("      --verbose or -v: show logs of what's happening\n");
  296.     printf("      --output file or -o file: save to a given file\n");
  297.     printf("      --timing: display the time used\n");
  298.     printf("      --repeat: run the transformation 20 times\n");
  299.     printf("      --debug: dump the tree of the result instead\n");
  300.     printf("      --novalid: skip the Dtd loading phase\n");
  301.     printf("      --noout: do not dump the result\n");
  302.     printf("      --maxdepth val : increase the maximum depth\n");
  303. #ifdef LIBXML_HTML_ENABLED
  304.     printf("      --html: the input document is(are) an HTML file(s)\n");
  305. #endif
  306. #ifdef LIBXML_DOCB_ENABLED
  307.     printf("      --docbook: the input document is SGML docbook\n");
  308. #endif
  309.     printf("      --param name value : pass a (parameter,value) pair\n");
  310.     printf("            string values must be quoted like \"'string'\"\n");
  311.     printf("      --nonet refuse to fetch DTDs or entities over network\n");
  312. #ifdef LIBXML_CATALOG_ENABLED
  313.     printf("      --catalogs : use the catalogs from $SGML_CATALOG_FILES\n");
  314. #endif
  315. #ifdef LIBXML_XINCLUDE_ENABLED
  316.     printf("      --xinclude : do XInclude processing on document intput\n");
  317. #endif
  318.     printf("      --profile or --norman : dump profiling informations \n");
  319. }
  320.  
  321. int
  322. main(int argc, char **argv)
  323. {
  324.     int i;
  325.     xsltStylesheetPtr cur = NULL;
  326.     xmlDocPtr doc, style;
  327.  
  328.     if (argc <= 1) {
  329.         usage(argv[0]);
  330.         return (1);
  331.     }
  332.  
  333.     xmlInitMemory();
  334.  
  335.     LIBXML_TEST_VERSION
  336.  
  337.     xmlLineNumbersDefault(1);
  338.  
  339.     if (novalid == 0)
  340.         xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS;
  341.     else
  342.         xmlLoadExtDtdDefaultValue = 0;
  343.     for (i = 1; i < argc; i++) {
  344.         if (!strcmp(argv[i], "-"))
  345.             break;
  346.  
  347.         if (argv[i][0] != '-')
  348.             continue;
  349. #ifdef LIBXML_DEBUG_ENABLED
  350.         if ((!strcmp(argv[i], "-debug")) || (!strcmp(argv[i], "--debug"))) {
  351.             debug++;
  352.         } else
  353. #endif
  354.         if ((!strcmp(argv[i], "-v")) ||
  355.                 (!strcmp(argv[i], "-verbose")) ||
  356.                 (!strcmp(argv[i], "--verbose"))) {
  357.             xsltSetGenericDebugFunc(stderr, NULL);
  358.         } else if ((!strcmp(argv[i], "-o")) ||
  359.                    (!strcmp(argv[i], "-output")) ||
  360.                    (!strcmp(argv[i], "--output"))) {
  361.             i++;
  362.             output = argv[i++];
  363.         } else if ((!strcmp(argv[i], "-V")) ||
  364.                    (!strcmp(argv[i], "-version")) ||
  365.                    (!strcmp(argv[i], "--version"))) {
  366.             printf("Using libxml %s, libxslt %s and libexslt %s\n",
  367.                    xmlParserVersion, xsltEngineVersion, exsltLibraryVersion);
  368.             printf
  369.     ("xsltproc was compiled against libxml %d, libxslt %d and libexslt %d\n",
  370.                  LIBXML_VERSION, LIBXSLT_VERSION, LIBEXSLT_VERSION);
  371.             printf("libxslt %d was compiled against libxml %d\n",
  372.                    xsltLibxsltVersion, xsltLibxmlVersion);
  373.             printf("libexslt %d was compiled against libxml %d\n",
  374.                    exsltLibexsltVersion, exsltLibxmlVersion);
  375.         } else if ((!strcmp(argv[i], "-repeat"))
  376.                    || (!strcmp(argv[i], "--repeat"))) {
  377.             if (repeat == 0)
  378.                 repeat = 20;
  379.             else
  380.                 repeat = 100;
  381.         } else if ((!strcmp(argv[i], "-novalid")) ||
  382.                    (!strcmp(argv[i], "--novalid"))) {
  383.             novalid++;
  384.         } else if ((!strcmp(argv[i], "-noout")) ||
  385.                    (!strcmp(argv[i], "--noout"))) {
  386.             noout++;
  387. #ifdef LIBXML_DOCB_ENABLED
  388.         } else if ((!strcmp(argv[i], "-docbook")) ||
  389.                    (!strcmp(argv[i], "--docbook"))) {
  390.             docbook++;
  391. #endif
  392. #ifdef LIBXML_HTML_ENABLED
  393.         } else if ((!strcmp(argv[i], "-html")) ||
  394.                    (!strcmp(argv[i], "--html"))) {
  395.             html++;
  396. #endif
  397.         } else if ((!strcmp(argv[i], "-timing")) ||
  398.                    (!strcmp(argv[i], "--timing"))) {
  399.             timing++;
  400.         } else if ((!strcmp(argv[i], "-profile")) ||
  401.                    (!strcmp(argv[i], "--profile"))) {
  402.             profile++;
  403.         } else if ((!strcmp(argv[i], "-norman")) ||
  404.                    (!strcmp(argv[i], "--norman"))) {
  405.             profile++;
  406.         } else if ((!strcmp(argv[i], "-nonet")) ||
  407.                    (!strcmp(argv[i], "--nonet"))) {
  408.             xmlSetExternalEntityLoader(xmlNoNetExternalEntityLoader);
  409. #ifdef LIBXML_CATALOG_ENABLED
  410.         } else if ((!strcmp(argv[i], "-catalogs")) ||
  411.                    (!strcmp(argv[i], "--catalogs"))) {
  412.             const char *catalogs;
  413.  
  414.             catalogs = getenv("SGML_CATALOG_FILES");
  415.             if (catalogs == NULL) {
  416.                 fprintf(stderr, "Variable $SGML_CATALOG_FILES not set\n");
  417.             } else {
  418.                 xmlLoadCatalogs(catalogs);
  419.             }
  420. #endif
  421. #ifdef LIBXML_XINCLUDE_ENABLED
  422.         } else if ((!strcmp(argv[i], "-xinclude")) ||
  423.                    (!strcmp(argv[i], "--xinclude"))) {
  424.             xinclude++;
  425.             xsltSetXIncludeDefault(1);
  426. #endif
  427.         } else if ((!strcmp(argv[i], "-param")) ||
  428.                    (!strcmp(argv[i], "--param"))) {
  429.             i++;
  430.             params[nbparams++] = argv[i++];
  431.             params[nbparams++] = argv[i];
  432.             if (nbparams >= 16) {
  433.                 fprintf(stderr, "too many params\n");
  434.                 return (1);
  435.             }
  436.         } else if ((!strcmp(argv[i], "-maxdepth")) ||
  437.                    (!strcmp(argv[i], "--maxdepth"))) {
  438.             int value;
  439.  
  440.             i++;
  441.             if (sscanf(argv[i], "%d", &value) == 1) {
  442.                 if (value > 0)
  443.                     xsltMaxDepth = value;
  444.             }
  445.         } else {
  446.             fprintf(stderr, "Unknown option %s\n", argv[i]);
  447.             usage(argv[0]);
  448.             return (1);
  449.         }
  450.     }
  451.     params[nbparams] = NULL;
  452.  
  453.     /*
  454.      * Replace entities with their content.
  455.      */
  456.     xmlSubstituteEntitiesDefault(1);
  457.  
  458.     /*
  459.      * Register the EXSLT extensions and the test module
  460.      */
  461.     exsltRegisterAll();
  462.     xsltRegisterTestModule();
  463.  
  464.     for (i = 1; i < argc; i++) {
  465.         if ((!strcmp(argv[i], "-maxdepth")) ||
  466.             (!strcmp(argv[i], "--maxdepth"))) {
  467.             i++;
  468.             continue;
  469.         } else if ((!strcmp(argv[i], "-o")) ||
  470.                    (!strcmp(argv[i], "-output")) ||
  471.                    (!strcmp(argv[i], "--output"))) {
  472.             i++;
  473.         continue;
  474.     }
  475.         if ((!strcmp(argv[i], "-param")) || (!strcmp(argv[i], "--param"))) {
  476.             i += 2;
  477.             continue;
  478.         }
  479.         if ((argv[i][0] != '-') || (strcmp(argv[i], "-") == 0)) {
  480.             if (timing)
  481.                 startTimer();
  482.         style = xmlParseFile((const char *) argv[i]);
  483.             if (timing) 
  484.         endTimer("Parsing stylesheet %s", argv[i]);
  485.         if (style == NULL) {
  486.         fprintf(stderr,  "cannot parse %s\n", argv[i]);
  487.         cur = NULL;
  488.         } else {
  489.         cur = xsltLoadStylesheetPI(style);
  490.         if (cur != NULL) {
  491.             /* it is an embedded stylesheet */
  492.             xsltProcess(style, cur, argv[i]);
  493.             xsltFreeStylesheet(cur);
  494.             goto done;
  495.         }
  496.         cur = xsltParseStylesheetDoc(style);
  497.         if (cur != NULL) {
  498.             if (cur->indent == 1)
  499.             xmlIndentTreeOutput = 1;
  500.             else
  501.             xmlIndentTreeOutput = 0;
  502.             i++;
  503.         } else {
  504.             xmlFreeDoc(style);
  505.             goto done;
  506.         }
  507.         }
  508.             break;
  509.  
  510.         }
  511.     }
  512.  
  513.     /*
  514.      * disable CDATA from being built in the document tree
  515.      */
  516.     xmlDefaultSAXHandlerInit();
  517.     xmlDefaultSAXHandler.cdataBlock = NULL;
  518.  
  519.     if ((cur != NULL) && (cur->errors == 0)) {
  520.         for (; i < argc; i++) {
  521.         doc = NULL;
  522.             if (timing)
  523.                 startTimer();
  524. #ifdef LIBXML_HTML_ENABLED
  525.             if (html)
  526.                 doc = htmlParseFile(argv[i], NULL);
  527.             else
  528. #endif
  529. #ifdef LIBXML_DOCB_ENABLED
  530.             if (docbook)
  531.                 doc = docbParseFile(argv[i], NULL);
  532.             else
  533. #endif
  534.                 doc = xmlParseFile(argv[i]);
  535.             if (doc == NULL) {
  536.                 fprintf(stderr, "unable to parse %s\n", argv[i]);
  537.                 continue;
  538.             }
  539.             if (timing)
  540.         endTimer("Parsing document %s", argv[i]);
  541.         xsltProcess(doc, cur, argv[i]);
  542.         }
  543.     }
  544.     if (cur != NULL)
  545.         xsltFreeStylesheet(cur);
  546. done:
  547.     xsltCleanupGlobals();
  548.     xmlCleanupParser();
  549.     xmlMemoryDump();
  550.     return (0);
  551. }
  552.  
  553.